/* $RCSFile: ListDataType.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/DataTypes/ListDataType.cs $
 * $log$
 * Revision 19 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 19 2011/02/22 01:22:14  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 6 2010/08/06 19:56:29  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Reflection;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.ComponentModel;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;

using AddonNice.Diagnostics;
using AddonNice.UI;
using AddonNice.UI.WebControls;
using AddonNice.Configuration;

using Telerik.Web.UI;


namespace AddonNice.UI.DataTypes
{
#if DEBUG
	public class DbgRadComboBox : RadComboBox
	{
		public DbgRadComboBox()
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox Ctor Called.",SettingsTraceSwitch.Sw.Info);
		}
		protected override void LoadViewState(object savedState)
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DbgRadComboBox LoadViewState BEG savedState: {0}",savedState),SettingsTraceSwitch.Sw.Info);
			base.LoadViewState(savedState);
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox LoadViewState END.",SettingsTraceSwitch.Sw.Info);
		}

		protected override object SaveViewState()
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DbgRadComboBox SaveViewState BEG ID: {0}",ID),SettingsTraceSwitch.Sw.Info);
			object ob   = base.SaveViewState();
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox SaveViewState END.",SettingsTraceSwitch.Sw.Info);
			return ob;
		}
		protected override void TrackViewState()
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox TrackViewState BEG.",SettingsTraceSwitch.Sw.Info);
			base.TrackViewState();
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox TrackViewState END.",SettingsTraceSwitch.Sw.Info);
		}
		
		protected override void Render(HtmlTextWriter writer)
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox Render BEG.",SettingsTraceSwitch.Sw.Info);
			base.Render(writer);
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox Render END.",SettingsTraceSwitch.Sw.Info);
		}
		protected override void OnUnload(EventArgs e)
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox OnUnload BEG.",SettingsTraceSwitch.Sw.Info);
			base.OnUnload(e);
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox OnUnload END.",SettingsTraceSwitch.Sw.Info);
		}
		protected override void RegisterScriptControl()
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox RegisterScriptControl BEG.",SettingsTraceSwitch.Sw.Info);
			base.RegisterScriptControl();
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox RegisterScriptControl END.",SettingsTraceSwitch.Sw.Info);
		}
		protected override void CreateChildControls()
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox CreateChildControls BEG.",SettingsTraceSwitch.Sw.Info);
			base.CreateChildControls();
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox CreateChildControlsl END.",SettingsTraceSwitch.Sw.Info);
		}
		protected override void OnPreRender(EventArgs e)
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox OnPreRender BEG.",SettingsTraceSwitch.Sw.Info);
			base.OnPreRender(e);
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox OnPreRender END.",SettingsTraceSwitch.Sw.Info);
		}

		protected override void OnLoad(EventArgs e)
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DbgRadComboBox OnLoad BEG IsPostBack: {0}",Page.IsPostBack),SettingsTraceSwitch.Sw.Info);
			base.OnLoad(e);
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox OnLoad END.",SettingsTraceSwitch.Sw.Info);
		}

		protected override void OnInit(EventArgs e)
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox OnInit BEG.",SettingsTraceSwitch.Sw.Info);
			base.OnInit(e);
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox OnInit END.",SettingsTraceSwitch.Sw.Info);
		}


		public override void DataBind()
		{
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DbgRadComboBox DataBind BEG ID: {0}.",ID),SettingsTraceSwitch.Sw.Info);
			base.DataBind();
			if ( SettingsTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]DbgRadComboBox DataBind END.",SettingsTraceSwitch.Sw.Info);
		}
	}
	
#endif // DEBUG    
	
	public delegate void NeedDataEventHandler(BaseDataType sender,EventArgs ev);

	/// <summary>
	/// ListDataType
	/// </summary>
	public class ListDataType : BaseDataType
	{
		protected string _dataValueField        =   string.Empty;
		protected string _dataTextField         =   string.Empty;
		protected string _CrmEntity             =   string.Empty;
		
		protected RadComboBoxSort _sortOrder    =   RadComboBoxSort.None;
		protected bool _SortCaseSensitive       =   false;

		public event NeedDataEventHandler NeedDataEvent;

		/// <summary>
		/// Property reserved to RadCombobox
		/// </summary>
		public RadComboBoxSort SortOrder
		{
			get
			{
				return _sortOrder;
			}
			set
			{
				_sortOrder  =   value;
			}
		}

		public bool SortCaseSensitive 
		{
			get
			{
				return _SortCaseSensitive;
			}
			set
			{
				_SortCaseSensitive  =   value;
			}
		}

		public override bool HasCrmEntity
		{
			get
			{
				return !string.IsNullOrEmpty(_CrmEntity);
			}
		}

		public override string CrmEntity
		{
			get
			{
				return _CrmEntity;
			}
			set
			{
				_CrmEntity  =   value;
			}
		}
		
		public override string DataValueField
		{
			get
			{
				return _dataValueField;
			}
			set
			{
				_dataValueField = value;
			}
		}

		public override string DataTextField
		{
			get
			{
				return _dataTextField;
			}
			set
			{
				_dataTextField = value;
			}
		}
		

		public ListDataType()
		{
			InnerDataType   =   PropertiesDataType.List;
		}

		public ListDataType(string CsvList)
		{
			InnerDataType   =   PropertiesDataType.List;
			InnerDataSource =   CsvList;
		}

		/// <summary>
		/// Returning dropdown list databound to FileInfo[] array
		/// </summary>
		public ListDataType(FileInfo[] fileList)
		{
			InnerDataType   =   PropertiesDataType.List;
			InnerDataSource =   fileList;
		}

		/// <summary>
		/// Used to fill a list with enum values
		/// </summary>
		public ListDataType(Type type)
		{
			//use Reflection to get the fields in our enum
			//FieldInfo[] info    =   type.GetFields();
			List<string> names = new List<string>();
			foreach ( FieldInfo info in type.GetFields() )
			{
				if ( info.Name != "value__" ) // This kept showing up in the list. 
					names.Add(info.Name);
			}
			InnerDataSource = names;
		}
		
		protected override void InitializeComponents()
		{
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType InitializeComponents BEG description: {0}, UseRadControl: {1}", Description,_UsesRadControl),DataTypeTraceSwitch.Sw.Info);
			if (!UseRadControl)
			{
				//Dropdown list
				DropDownList dd         =   new DropDownList();
				dd.Width                =   controlWidth;
				if (HandleChanges)
				{
					if (DataTypeTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( "[V]ListDataType InitializeComponents HandleChanges set", DataTypeTraceSwitch.Sw.Info);
					dd.AutoPostBack     =   true;
					dd.SelectedIndexChanged += new EventHandler(dd_SelectedIndexChanged);
				}
				dd.DataSource           =   DataSource;
				dd.DataValueField       =   DataValueField;
				dd.DataTextField        =   DataTextField;
				if ( ReadOnly )
					dd.Enabled          =   false;
				innerControl            =   dd;
			}
			else
			{
				//RadComboBox
#if DEBUG
				DbgRadComboBox dd = new DbgRadComboBox();
#else
				RadComboBox dd          =   new RadComboBox ();
#endif // DEBUG
				dd.Width                =   controlWidth;
				dd.Sort                 =   SortOrder;
				dd.SortCaseSensitive    =   SortCaseSensitive;
				if (HandleChanges)
				{
					if (DataTypeTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( "[V]ListDataType InitializeComponents HandleChanges set", DataTypeTraceSwitch.Sw.Info);
					dd.AutoPostBack     =   true;
					dd.SelectedIndexChanged +=new RadComboBoxSelectedIndexChangedEventHandler(dd_RadSelectedIndexChanged);
				}
				dd.DataSource           =   DataSource;
				dd.DataValueField       =   DataValueField;
				dd.DataTextField        =   DataTextField;
				if ( ReadOnly )
					dd.Enabled          =   false;
				innerControl            =   dd;
			}
			_IsInitialized              =   true;
		}


		void dd_SelectedIndexChanged(object sender, EventArgs e)
		{
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType dd_SelectedIndexChanged sender: {0}",sender),DataTypeTraceSwitch.Sw.Info);
			string oldValue         =   Val;
			ReadDataFromEditControl();
			string newValue         =   Val;
			OnDataTypeEvent(new DataTypeEventArgs(DataTypeEventType.Changed,sender,e,oldValue,newValue));
		}

		void dd_RadSelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
		{
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType dd_RadSelectedIndexChanged sender: {0}",sender),DataTypeTraceSwitch.Sw.Info);
			string oldValue         =   Val;
			ReadDataFromEditControl();
			string newValue         =   Val;
			OnDataTypeEvent(new DataTypeEventArgs(DataTypeEventType.Changed,sender,e,oldValue,newValue));
		}
				
		public void OnNeedData(EventArgs ev)
		{
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType OnNeedData BEG NeedDataEvent null: {0}", ( NeedDataEvent == null )),DataTypeTraceSwitch.Sw.Info);
			if ( NeedDataEvent != null )
				NeedDataEvent(this,ev);
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]ListDataType OnNeedData END.",DataTypeTraceSwitch.Sw.Info);
		}

		public override object DataSource
		{
			get
			{
				if ( DataTypeTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType DataSource GET InnerDataSource null: {0}", ( InnerDataSource == null )),DataTypeTraceSwitch.Sw.Info);
				if ( InnerDataSource == null )
					OnNeedData(new EventArgs());
				if( InnerDataSource != null)
				{
					if(InnerDataSource is FileInfo[])
						return InnerDataSource;
					if(InnerDataSource is List<string>)
						return InnerDataSource;
					return InnerDataSource.ToString().Split(';');
					}
				return null;
			}
			set
			{
				if ( DataTypeTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType DataSource SET value null: {0}", ( value == null )),DataTypeTraceSwitch.Sw.Info);
				InnerDataSource = value;
			}
		}

		public override void ResetDataSource(object newDataSrc,string SelVal)
		{
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType ResetDataSource BEG newDataSrc: {0}, SelVal: {1}", newDataSrc,( SelVal == null )? string.Empty:SelVal),DataTypeTraceSwitch.Sw.Info);
			InnerDataSource =   newDataSrc;
			// Val.set will do a databind
			if ( !string.IsNullOrEmpty(SelVal))
					Val     =   SelVal;
			else    Val     =   string.Empty;
			if ( HandleChanges )
				OnDataTypeEvent(new DataTypeEventArgs(DataTypeEventType.ReBound,this));
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType ResetDataSource END innerControl null: {0}", innerControl == null ),DataTypeTraceSwitch.Sw.Info);
		}

		public override void DataBind()
		{
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType DataBind BEG for: {0}, UseRadControl: {1}", this,UseRadControl),DataTypeTraceSwitch.Sw.Info);
			try
			{
				if (!UseRadControl)
				{
					DropDownList dd     = (DropDownList)innerControl;
					dd.ClearSelection();
					dd.Items.Clear();
					dd.DataSource       =   DataSource;
					dd.DataValueField   =   DataValueField;
					dd.DataTextField    =   DataTextField;
					dd.DataBind();
					ListItem it         =   dd.Items.FindByValue(Val);
					if (it != null)
						it.Selected     =   true;
					if ( DataTypeTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType DataBind select: [{0}], Success: {1}", Val,it != null),DataTypeTraceSwitch.Sw.Info);
				}
				else
				{
					RadComboBox dd      =   (RadComboBox)innerControl;
					dd.ClearSelection();
					dd.Items.Clear();
					dd.DataValueField   =   DataValueField;
					dd.DataTextField    =   DataTextField;
					dd.DataSource       =   DataSource;
					dd.DataBind();
					if ( dd.Sort != RadComboBoxSort.None )
						dd.SortItems();
					RadComboBoxItem it  =   dd.Items.FindItemByValue(Val);
					if (it != null)
						it.Selected     =   true;
					if ( DataTypeTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType Rad DataBind select: [{0}], Success: {1}", Val,it != null),DataTypeTraceSwitch.Sw.Info);
				}
			}
			catch (Exception ex)
			{
				if ( DataTypeTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ListDataType DataBind ex: {0}",ex),DataTypeTraceSwitch.Sw.Info);
				throw;
			}
			if ( DataTypeTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]ListDataType DataBind END.",DataTypeTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Update value from control: used by eventhandler after a control change event triggered
		/// </summary>
		/// <returns></returns>
		public override string ReadDataFromEditControl()
		{
			Control Ctl =   EditControl;
			if (DataTypeTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType ReadDataFromEditControl BEG Control is null: {0}, Val: {1}.", (Ctl == null), Val ), DataTypeTraceSwitch.Sw.Info);
			if ( Ctl ==   null )
				return Val;
			// DO NOT use Val which is doing a databind on set but use InnerValue
			if (!UseRadControl)
			{
				if ( Ctl is DropDownList)
				{
					//Update value from control
					DropDownList dd     =   (DropDownList)Ctl;
					if (dd.SelectedItem != null)
						innerValue      =   dd.SelectedItem.Value;
					else innerValue     =   string.Empty;
				}
			}
			else
			{
				if ( Ctl is RadComboBox)
				{
					RadComboBox dd      =   (RadComboBox)Ctl;
					if (dd.SelectedItem != null)
						innerValue      = dd.SelectedItem.Value;
					else innerValue     = string.Empty;
				}
			}
			if (DataTypeTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType ReadDataFromEditControl END InnerValue: {0}.", innerValue), DataTypeTraceSwitch.Sw.Info);
			return Val;
		}

		public override Control EditControl
		{
			get
			{
				if ( DataTypeTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType EditControl GET innerControl is NULL: {0}.",(innerControl == null)),DataTypeTraceSwitch.Sw.Info);
				if (innerControl == null)
					InitializeComponents();
				return innerControl;
			}
			set
			{
				bool nodif        = (innerControl != null) && innerControl.Equals(value);
				if (DataTypeTraceSwitch.Sw.TraceVerbose)
				{
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType EditControl SET innerControl is NULL: {0}", innerControl == null ), DataTypeTraceSwitch.Sw.Info);
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType EditControl SET innerControl equal to value : {0}", nodif), DataTypeTraceSwitch.Sw.Info);
				}
						
				if (!UseRadControl)
				{
					if (value is DropDownList)
					{
						//Update value from control
						DropDownList dd     = (DropDownList)value;
						dd.DataValueField   = DataValueField;
						dd.DataTextField    = DataTextField;
						if (HandleChanges && !dd.AutoPostBack)
						{
							dd.AutoPostBack = true;
							dd.SelectedIndexChanged += new EventHandler(dd_SelectedIndexChanged);
						}
						// DO NOT use Val but use InnerValue
						if (dd.SelectedItem != null)
							innerValue      = dd.SelectedItem.Value;
						else innerValue     = string.Empty;
						if ( !nodif )
							innerControl        = value;
						return;
					}
				}
				else
				{
					if (value is RadComboBox)
					{
						//Update value from control
						RadComboBox dd      = (RadComboBox)value;
						dd.DataValueField   = DataValueField;
						dd.DataTextField    = DataTextField;
						if (HandleChanges && !dd.AutoPostBack)
						{
							dd.AutoPostBack = true;
							dd.SelectedIndexChanged  += new RadComboBoxSelectedIndexChangedEventHandler(dd_RadSelectedIndexChanged);
						}
						// DO NOT use Value but use InnerValue
						if (dd.SelectedItem != null)
							innerValue      = dd.SelectedItem.Value;
						else innerValue     = string.Empty;
						if ( !nodif )
							innerControl        = value;
						return;
					}
				}

				string ErrMsg   =  string.Format("[E]ListDataType EditControl A DropDownList values is required, a '{0} is given",value.GetType().Name);
				if ( DataTypeTraceSwitch.Sw.TraceError )
					Trace.WriteLine(ErrMsg,DataTypeTraceSwitch.Sw.Info);
				throw new ArgumentException(ErrMsg);
			}
		}


		public override string Val
		{
			get
			{
				return innerValue;
			}
			set
			{
				if ( DataTypeTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType Val SET BEG value: [{0}]", value),DataTypeTraceSwitch.Sw.Info);
				innerValue      = value;
				if ( DataTypeTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ListDataType Val SET innerControl is NULL: {0}", innerControl == null ),DataTypeTraceSwitch.Sw.Info);
				if ( innerControl == null )
					return;
				//update value in control
				DataBind();
				if ( DataTypeTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine("[V]ListDataType Val END.",DataTypeTraceSwitch.Sw.Info);
			}
		}
	}
}